package com.cdck.safe.dete.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cdck.safe.dete.common.exception.BusinessException;
import com.cdck.safe.dete.common.util.SecurityUtils;
import com.cdck.safe.dete.mapper.ResourceMapper;
import com.cdck.safe.dete.model.entity.BookRecord;
import com.cdck.safe.dete.model.entity.Booking;
import com.cdck.safe.dete.model.entity.ResourceRecord;
import com.cdck.safe.dete.mapper.ResourceRecordMapper;
import com.cdck.safe.dete.model.entity.SysUser;
import com.cdck.safe.dete.model.query.BaseKeywordsQuery;
import com.cdck.safe.dete.model.query.ResourceRecordQuery;
import com.cdck.safe.dete.model.vo.ResourceRecordVO;
import com.cdck.safe.dete.service.ResourceRecordService;
import com.cdck.safe.dete.service.ResourceService;
import com.cdck.safe.dete.service.SysMenuService;
import com.cdck.safe.dete.service.SysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;

import javax.annotation.Resource;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * (ResourceRecord)表服务实现类
 *
 * @author wp
 * @since 2024-05-18 14:35:52
 */
@Service
@RequiredArgsConstructor
public class ResourceRecordServiceImpl extends ServiceImpl<ResourceRecordMapper, ResourceRecord> implements ResourceRecordService {


    @Resource
    ResourceMapper resourceMapper;

    @Resource
    SysUserService sysUserService;
//
//    @Resource
//    ResourceMapper resourceMapper;

    @Resource
    ResourceRecordMapper resourceRecordMapper;
    /**
     * 通过ID查询单条数据
     *
     * @param id 主键
     * @return 实例对象
     */
    @Override
    public ResourceRecord getResourceRecordFormData(Long id) {
        return this.getById(id);
    }

    /**
     * 分页查询
     *
     * queryParams 筛选条件
     * @return 查询结果
     */

    @Override
    public IPage<ResourceRecordVO> queryList(ResourceRecordQuery queryParams) {
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        Page<ResourceRecord> page = new Page<>(pageNum, pageSize);
        Page<ResourceRecordVO> pageVO = new Page<>(pageNum, pageSize);


        Page<ResourceRecord> recordPage = this.page(
                page,
                new LambdaQueryWrapper<ResourceRecord>().eq(ResourceRecord::getStatus,0)
        );
        List<ResourceRecordVO> recordVOList = recordPage.getRecords().stream().map(item -> {
            ResourceRecordVO vo = new ResourceRecordVO();
            BeanUtils.copyProperties(item, vo);
            vo.setStatusDesc(getStatusDesc(item.getStatus()));
            SysUser sysUser = sysUserService.getById(item.getUserId());
            if (sysUser != null) {
                vo.setUserName(sysUser.getNickname());
            }
            com.cdck.safe.dete.model.entity.Resource resource = resourceMapper.selectById(item.getResourceId());
            if (resource != null) {
                vo.setResourceName(resource.getName());
            }

            SysUser applicationUser = sysUserService.getById(item.getApplicationId());
            if (applicationUser != null) {
                vo.setUserName(applicationUser.getNickname());
            }
            return vo;
        }).collect(Collectors.toList());
        BeanUtils.copyProperties(recordPage, pageVO, "records");
        pageVO.setRecords(recordVOList);
        return pageVO;
    }

    @Override
    public List<ResourceRecordVO> myRecord() {
        Long myUserId = SecurityUtils.getUserId();
        List<ResourceRecord> list = this.list(new LambdaQueryWrapper<ResourceRecord>().eq(ResourceRecord::getUserId, myUserId));

        List<ResourceRecordVO> recordVOList = list.stream().map(item -> {
            ResourceRecordVO vo = new ResourceRecordVO();
            BeanUtils.copyProperties(item, vo);
            vo.setStatusDesc(getStatusDesc(item.getStatus()));
            SysUser sysUser = sysUserService.getById(item.getUserId());
            if (sysUser != null) {
                vo.setUserName(sysUser.getNickname());
            }
            com.cdck.safe.dete.model.entity.Resource resource = resourceMapper.selectById(item.getResourceId());
            if (resource != null) {
                vo.setResourceName(resource.getName());
            }

            SysUser applicationUser = sysUserService.getById(item.getApplicationId());
            if (applicationUser != null) {
                vo.setUserName(applicationUser.getNickname());
            }
            return vo;
        }).collect(Collectors.toList());
        return recordVOList;
    }

    @Override
    public IPage<ResourceRecordVO> queryByPage(ResourceRecordQuery queryParams){
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        Page<ResourceRecord> page = new Page<>(pageNum, pageSize);
        Page<ResourceRecordVO> pageVO = new Page<>(pageNum, pageSize);


        Page<ResourceRecord> recordPage = this.page(
                page,
                new LambdaQueryWrapper<>()
        );
        List<ResourceRecordVO> recordVOList = recordPage.getRecords().stream().map(item -> {
            ResourceRecordVO vo = new ResourceRecordVO();
            BeanUtils.copyProperties(item, vo);
            vo.setStatusDesc(getStatusDesc(item.getStatus()));
            SysUser sysUser = sysUserService.getById(item.getUserId());
            if (sysUser != null) {
                vo.setUserName(sysUser.getNickname());
            }
            Long resourceId = item.getResourceId();
            com.cdck.safe.dete.model.entity.Resource resource = resourceMapper.selectById(resourceId);
            if (resource != null) {
                vo.setResourceName(resource.getName());
            }

            SysUser applicationUser = sysUserService.getById(item.getApplicationId());
            if (applicationUser != null) {
                vo.setApplicationName(applicationUser.getNickname());
            }
            return vo;
        }).collect(Collectors.toList());
        BeanUtils.copyProperties(recordPage, pageVO, "records");
        pageVO.setRecords(recordVOList);
        return pageVO;
     }

     public String getStatusDesc(Integer status) {
        switch (status) {
            case 0:
                return "待审核";
            case 1:
                return "驳回";
            case 2:
                return "通过";
            case 3:
                return "完成";
            case 4:
                return "取消";
        }
         return "未知";
     }

    /**
     * 新增数据
     *
     * @param resourceRecord 实例对象
     * @return 实例对象
     */
    @Override
    public boolean saveResourceRecord(ResourceRecord resourceRecord) {
        resourceRecord.setStatus(0);
        resourceRecord.setUserId(SecurityUtils.getUserId());
        resourceRecord.setCreateTime(new Date());
        resourceRecord.setUpdateTime(new Date());
       return this.save(resourceRecord);
    }

    /**
     * 修改数据
     *
     * @param resourceRecord 实例对象
     * @return 实例对象
     */
    @Override
    public boolean updateResourceRecord(Long id, ResourceRecord resourceRecord) {
         return this.updateById(resourceRecord);
    }

    /**
     * 通过主键删除数据
     *
     * @param idsStr ids集合
     * @return 是否成功
     */
    @Override
    public boolean deleteResourceRecords(String idsStr) {
         Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的数据为空");
        // 逻辑删除
        List<Long> ids = Arrays.stream(idsStr.split(","))
                .map(Long::parseLong).collect(Collectors.toList());
        return this.removeByIds(ids);
    }

    @Override
    public boolean overrule(ResourceRecord record) {
        ResourceRecord resourceRecord = this.getById(record.getId());
        resourceRecord.setStatus(1);
        resourceRecord.setReason(record.getReason());
        return this.updateById(resourceRecord);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean pass(Long id) {
        ResourceRecord record = this.getById(id);
        if (record != null) {

            //查找这个作座位的所有预约记录
            LambdaQueryWrapper<ResourceRecord> bookingWrapper = new LambdaQueryWrapper<>();
            bookingWrapper
                    .eq(ResourceRecord::getStatus, 2)
                    .gt(ResourceRecord::getEndTime, LocalDateTime.now());
            List<ResourceRecord> recordList = this.list(bookingWrapper);
            if (recordList == null && recordList.size() == 0) {
                //没有预约记录，直接返回
                record.setStatus(2);
            }
            Boolean flag = true;
            for (ResourceRecord recordE : recordList) {
                //如果这个时间段，记录表里面有记录，且在使用范围，说明作为被占用
                long bookingStartTime = recordE.getStartTime().getTime();
                long bookingEndTime = recordE.getEndTime().getTime();
                long seatStartTime = record.getStartTime().getTime();
                long seatEndTime = record.getEndTime().getTime();

                // 检查预订与座位时间范围是否有交叉,三种情况
                if ((seatStartTime >= bookingStartTime && seatEndTime <= bookingEndTime)
                        || (seatStartTime <= bookingStartTime && seatEndTime >= bookingStartTime)
                        || (seatStartTime <= bookingEndTime && seatEndTime >= bookingEndTime)) {
                    flag = false;
                    throw new BusinessException("该资源在该时间段已被占用");
                }
            }
            if (flag) {
                record.setStatus(2);
            }

            record.setApplicationId(SecurityUtils.getUserId());
            return this.updateById(record);
        }
        return false;
    }

    @Override
    public boolean cancel(Long id) {
        ResourceRecord record = this.getById(id);
        if (record != null) {
            record.setStatus(4);
            return this.updateById(record);
        }
        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean finish(Long id) {
        // 修改对应记录完成时间
        ResourceRecord resourceRecord = resourceRecordMapper.selectOne(new LambdaQueryWrapper<ResourceRecord>()
                .eq(ResourceRecord::getId, id));
        resourceRecord.setRealEndTime(new Date());
        resourceRecordMapper.updateById(resourceRecord);
        ResourceRecord record = this.getById(id);
        if (record != null) {
            record.setStatus(3);
            return this.updateById(record);
        }
        return false;
    }
}
